(function (window, T) {
    var array = T.array = {};

    /**
     * 遍历数组中所有元素
     * @name array.each
     * @function
     * @grammar array.each(source, iterator[, thisObject])
     * @param {Array} source 需要遍历的数组
     * @param {Function} iterator 对每个数组元素进行调用的函数，该函数有三个参数，第一个为数组元素，第二个为数组索引值，第三个参数为需要处理的数组。function (item, index, source)。
     * @param {Object} [thisObject] 函数调用时的this指针，如果没有此参数，默认是当前遍历的数组
     * @remark
     * each方法不支持对Object的遍历,对Object的遍历使用object.each 。
     * @shortcut each
     * @meta standard
     *             
     * @returns {Array} 遍历的数组
     */
     
    array.forEach = function (source, iterator, thisObject) {
        var returnValue, item, i, len = source.length;
        
        if ('function' == typeof iterator) {
            for (i = 0; i < len; i++) {
                item = source[i];
                returnValue = iterator.call(thisObject, item, i, source);
        
                if (returnValue === false) {
                    break;
                }
            }
        }
        return source;
    }

    /**
     * 判断一个数组中是否所有元素都满足给定条件
     * @name array.every
     * @function
     * @grammar array.every(source, iterator[,thisObject])
     * @param {Array} source 需要判断的数组.
     * @param {Function} iterator 判断函数.
     * @param {Object} [thisObject] 函数调用时的this指针，如果没有此参数，默认是当前遍历的数组
     * @return {boolean} 判断结果.
     * @see array.some
     */
    array.every = function(source, iterator, thisObject) {
        var i = 0,
            len = source.length;
        for (; i < len; i++) {
            if (i in source && !iterator.call(thisObject, source[i], i, source)) {
                return false;
            }
        }
        return true;
    };

    /**
     * 从数组中筛选符合条件的元素
     * @name array.filter
     * @function
     * @grammar array.filter(source, iterator[, thisObject])
     * @param {Array} source 需要筛选的数组
     * @param {Function} iterator 对每个数组元素进行筛选的函数，该函数有三个参数，第一个为数组元素，第二个为数组索引值，function (item, index)，函数需要返回true或false，第三个参数为需要筛选的数组
     * @param {Object} [thisObject] 函数调用时的this指针，如果没有此参数，默认是当前遍历的数组
     * @meta standard
     * @see array.find
     *             
     * @returns {Array} 符合条件的数组项集合
     */

    array.filter = function (source, iterator, thisObject) {
        var result = [],
            resultIndex = 0,
            len = source.length,
            item,
            i;
        
        if ('function' == typeof iterator) {
            for (i = 0; i < len; i++) {
                item = source[i];
                //TODO
                //和标准不符，see array.each
                if (true === iterator.call(thisObject, item, i, source)) {
                    // resultIndex用于优化对result.length的多次读取
                    result[resultIndex++] = item;
                }
            }
        }
        
        return result;
    };

    /**
     * 查询数组中指定元素的索引位置
     * @name array.indexOf
     * @function
     * @grammar array.indexOf(source, match[, fromIndex])
     * @param {Array} source 需要查询的数组
     * @param {Any} match 查询项
     * @param {number} [fromIndex] 查询的起始位索引位置，如果为负数，则从source.length+fromIndex往后开始查找
     * @see array.find,array.lastIndexOf
     *             
     * @returns {number} 指定元素的索引位置，查询不到时返回-1
     */
    array.indexOf = function (source, match, fromIndex) {
        var len = source.length,
            iterator = match;
            
        fromIndex = fromIndex | 0;
        if(fromIndex < 0){//小于0
            fromIndex = Math.max(0, len + fromIndex)
        }
        for ( ; fromIndex < len; fromIndex++) {
            if(fromIndex in source && source[fromIndex] === match) {
                return fromIndex;
            }
        }
        
        return -1;
    };

    /**
     * 从后往前，查询数组中指定元素的索引位置
     * @name array.lastIndexOf
     * @function
     * @grammar array.lastIndexOf(source, match)
     * @param {Array} source 需要查询的数组
     * @param {Any} match 查询项
     * @param {number} [fromIndex] 查询的起始位索引位置，如果为负数，则从source.length+fromIndex往前开始查找
     * @see array.indexOf
     *             
     * @returns {number} 指定元素的索引位置，查询不到时返回-1
     */

    array.lastIndexOf = function (source, match, fromIndex) {
        var len = source.length;

        fromIndex = fromIndex | 0;

        if(!fromIndex || fromIndex >= len){
            fromIndex = len - 1;
        }
        if(fromIndex < 0){
            fromIndex += len;
        }
        for(; fromIndex >= 0; fromIndex --){
            if(fromIndex in source && source[fromIndex] === match){
                return fromIndex;
            }
        }
        
        return -1;
    };

    /**
     * 遍历数组中所有元素，将每一个元素应用方法进行转换，并返回转换后的新数组。
     * @name array.map
     * @function
     * @grammar array.map(source, iterator[, thisObject])
     * @param {Array}    source   需要遍历的数组.
     * @param {Function} iterator 对每个数组元素进行处理的函数.
     * @param {Object} [thisObject] 函数调用时的this指针，如果没有此参数，默认是当前遍历的数组
     * @return {Array} map后的数组.
     * @see array.reduce
     */
    array.map = function(source, iterator, thisObject) {
        var results = [],
            i = 0,
            l = source.length;
        for (; i < l; i++) {
            results[i] = iterator.call(thisObject, source[i], i, source);
        }
        return results;
    };

    /**
     * 遍历数组中所有元素，将每一个元素应用方法进行合并，并返回合并后的结果。
     * @name array.reduce
     * @function
     * @grammar array.reduce(source, iterator[, initializer])
     * @param {Array}    source 需要遍历的数组.
     * @param {Function} iterator 对每个数组元素进行处理的函数，函数接受四个参数：上一次reduce的结果（或初始值），当前元素值，索引值，整个数组.
     * @param {Object}   [initializer] 合并的初始项，如果没有此参数，默认用数组中的第一个值作为初始值.
     * @return {Array} reduce后的值.
     * @version 1.3.4
     * @see array.reduce
     */
    array.reduce = function(source, iterator, initializer) {
        var i = 0,
            l = source.length,
            found = 0;

        if( arguments.length < 3){
            //没有initializer的情况，找到第一个可用的值
            for(; i < l; i++){
                initializer = source[i++];
                found = 1;
                break;
            }
            if(!found){
                return ;
            }
        }

        for (; i < l; i++) {
            if( i in source){
                initializer = iterator(initializer, source[i] , i , source);
            }
        }
        return initializer;
    };

    /**
     * 移除数组中的项
     * @name array.remove
     * @function
     * @grammar array.remove(source, match)
     * @param {Array} source 需要移除项的数组
     * @param {Any} match 要移除的项
     * @meta standard
     * @see array.removeAt
     *             
     * @returns {Array} 移除后的数组
     */
    array.remove = function (source, match) {
        var len = source.length;
            
        while (len--) {
            if (len in source && source[len] === match) {
                source.splice(len, 1);
            }
        }
        return source;
    };

    /**
     * 判断一个数组中是否有部分元素满足给定条件
     * @name array.some
     * @function
     * @grammar array.some(source, iterator[,thisObject])
     * @param {Array} source 需要判断的数组.
     * @param {Function} iterator 判断函数.
     * @param {Object} [thisObject] 函数调用时的this指针，如果没有此参数，默认是当前遍历的数组
     * @return {boolean} 判断结果.
     * @see array.every
     */
    array.some = function(source, iterator, thisObject) {
        var i = 0,
            len = source.length;
        for (; i < len; i++) {
            if (i in source && iterator.call(thisObject || source, source[i], i)) {
                return true;
            }
        }
        return false;
    };

    /**
     * 过滤数组中的相同项。如果两个元素相同，会删除后一个元素。
     * @name array.unique
     * @function
     * @grammar array.unique(source[, compareFn])
     * @param {Array} source 需要过滤相同项的数组
     * @param {Function} [compareFn] 比较两个数组项是否相同的函数,两个数组项作为函数的参数。
     *             
     * @returns {Array} 过滤后的新数组
     */
    array.unique = function (source, compareFn) {
        var len = source.length,
            result = source.slice(0),
            i, datum;
            
        if ('function' != typeof compareFn) {
            compareFn = function (item1, item2) {
                return item1 === item2;
            };
        }
        
        // 从后往前双重循环比较
        // 如果两个元素相同，删除后一个
        while (--len > 0) {
            datum = result[len];
            i = len;
            while (i--) {
                if (compareFn(datum, result[i])) {
                    result.splice(len, 1);
                    break;
                }
            }
        }

        return result;
    };

})(window, T);